#include "./placement_solver.h"
#include "./draw.h"
#include <iostream>
#include <fstream>
#include <vector>
#include <cstdio>
#include <ctime>
#include <cstdlib>

using namespace std;

// Generate cubes randomly
void Cube_Generater(vector<Cube> &cubes, int n, int size) {
	cubes.clear();
	for (int i = 1; i <= n; i++) 
		cubes.push_back(Cube(rand() % size + 1, rand() % size + 1, rand() % size + 1));
	return ;
}

// Generate testcase randomly
void Test_Generater() {
	for (int i = 0; i <= 30; i++) {
		char input_file[20];
		sprintf(input_file, "../data/input%d.txt", i);
		ofstream fout(input_file);
		vector<Cube> cubes;
		int cube_num = i * 3 + 10;
		Cube_Generater(cubes, cube_num, 10);
		fout << cube_num << endl;
		for (int i = 0; i < cube_num; i++) {
			fout << cubes[i].length << ' ' << cubes[i].width << ' ' << cubes[i].height << endl;
		}
		fout.close();
	}
	return ;
}

bool draw = false, calc = true;
int time_limitaion = 600;
string input_file = "input.txt", output_file = "output.txt";

// Check is there any overlap between cubes
bool check(vector<Cube> & cubes) {
	for (int i = 0; i < cubes.size(); i++)
		for (int j = i + 1; j < cubes.size(); j++)
			if (cubes[i].intersect(cubes[j])) {
				cout << "[error]	Cube [" << i << "] and Cube [" << j << "] are intersected. " << endl; 
				return false;
			}
	return true;
}

// Draw after solve
void Draw(const vector<Cube> & cubes, int argc, char *argv[])
{
	Draw::Instance()->LoadCubes(cubes);
	Draw::Instance()->Main(argc, argv);
}

// Draw from an existing file
void Draw(const string & File_Name, int argc, char *argv[])
{
	Draw::Instance()->LoadCubes(File_Name);
	Draw::Instance()->Main(argc, argv);
}

void Solve(vector<Cube> & cubes)
{
	Placement_Solver solver(time_limitaion);
	int start_time = clock();
	solver.LoadCube(input_file);
	solver.Solve();
	solver.Output(output_file);
	solver.GetCube(cubes);
	
	if (check(cubes)) cout << "The solution is legal!" << endl;
	else cout << "[error] The solution is illegal!" << endl;
	cout << "Total Runtime : " << (double) (clock() - start_time) / CLOCKS_PER_SEC << " s." << endl;

	return ;
}

void Test(int argc, char *argv[]) {
	
	vector<Cube> cubes;
	
	if (calc)
		Solve(cubes);

	if (draw) {
		if (calc)
			Draw(cubes, argc, argv);
		else
			Draw(output_file, argc, argv);
	}

	return ;
}

int main(int argc, char *argv[]) {
	for (int i = 1; i < argc; i++) {
		string opt = string(argv[i]);
		if (opt == "-LF") {  // assign input file name
			assert(i + 1 < argc);
			input_file = string(argv[i + 1]);
		}
		else if (opt == "-SF") {  // assign output file name
			assert(i + 1 < argc);
			output_file = string(argv[i + 1]);
		}
		else if (opt == "-D") {  // draw the solution after solve
			draw = true;
		}
		else if (opt == "-DO") {  // draw the solution from an existing file
			calc = false;         // should assign an output file using "-SF" first 
			draw = true;          // otherwise will load "output.txt"  
		}
		else if (opt == "-T") {   // assign a time limitation
			assert(i + 1 < argc); // the program will terminate in (time_limitation + 60) s
			time_limitaion = atoi(argv[i + 1]);
			assert(time_limitaion >= 1);
		}
	}
	//Test_Generater();
	Test(argc, argv);
	return 0;
}
